/////////////////////////////////////////////////////////////////////////////
// Name:        mainform.cpp
// Purpose:     
// Author:      Erwan Le Martelot
// Modified by: 
// Created:     18/04/2007 12:58:26
// RCS-ID:      
// Copyright:   
// Licence:     
/////////////////////////////////////////////////////////////////////////////

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "mainform.hpp"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

////@begin includes
////@end includes

#include "mainform.hpp"

// ----- My Includes ----- //
#include <wx/filedlg.h>
#include <wx/filename.h>
#include <wx/textdlg.h>
#include <exception>
#include "AssertionException.hpp"
#include "IOFileException.hpp"
#include "ANNPluginInterface.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include "wx/plot/plot.h"
#include "Statistics.hpp"
#include <wx/aboutdlg.h>
#include "Version.hpp"
#include "SCANN.xpm"
// ----------------------- //

// ---- My Namespaces ---- //
using namespace std;
using namespace Exceptions;
using namespace Toolkit;
using namespace wxToolkit;
using namespace SC;
// ----------------------- //

// Icon size
#define ICON_W	16
#define ICON_H	16

// Default display buffer value
#define DEFAULT_DSP_BUF_SIZE	1000

// Curves min and max values
#define CURVE_MIN	-1.1
#define CURVE_MAX	1.1

// No sample
#define NO_SAMPLE pair<int,int>(-2,-2)

// Convert clock time into ms
#define CLK_TO_MS(X) ( ((X)*1000) / CLOCKS_PER_SEC )

////@begin XPM images
#include "SCANN_icon.xpm"
#include "open.xpm"
#include "load_from.xpm"
#include "save_to.xpm"
#include "forward.xpm"
#include "exit.xpm"
#include "plugin_dir.xpm"
#include "help.xpm"
////@end XPM images

/*!
 * MainForm type definition
 */

IMPLEMENT_CLASS( MainForm, wxFrame )

/*!
 * MainForm event table definition
 */

BEGIN_EVENT_TABLE( MainForm, wxFrame )

////@begin MainForm event table entries
	EVT_SIZE( MainForm::OnSize )
	EVT_IDLE( MainForm::OnIdle )

	EVT_MENU( ID_LOAD_PROGRAM_MENUITEM, MainForm::OnLoadProgramMenuitemClick )

	EVT_MENU( ID_LOAD_DATA_MENUITEM, MainForm::OnLoadDataMenuitemClick )

	EVT_MENU( ID_SAVE_DATA_MENUITEM, MainForm::OnSaveDataMenuitemClick )

	EVT_MENU( ID_EXPORT_RESULTS_MENUITEM, MainForm::OnExportResultsMenuitemClick )

	EVT_MENU( ID_QUIT_MENUITEM, MainForm::OnQuitMenuitemClick )

	EVT_MENU( ID_PLUGIN_DIR_MENUITEM, MainForm::OnPluginDirMenuitemClick )

	EVT_MENU( wxID_ABOUT, MainForm::OnAboutClick )

	EVT_SPLITTER_SASH_POS_CHANGED( ID_MAIN_SPLITTERWINDOW, MainForm::OnMainSplitterwindowSashPosChanged )

	EVT_BUTTON( ID_LOAD_PROGRAM_BUTTON, MainForm::OnLoadProgramButtonClick )

	EVT_TOGGLEBUTTON( ID_RUN_TOGGLEBUTTON, MainForm::OnRunTogglebuttonClick )

	EVT_BUTTON( ID_RESET_BUTTON, MainForm::OnResetButtonClick )

	EVT_BUTTON( ID_SHOW_SYSTEMS_BUTTON, MainForm::OnShowSystemsButtonClick )

	EVT_BUTTON( ID_ADD_SET_BUTTON, MainForm::OnAddSetButtonClick )

	EVT_BUTTON( ID_REMOVE_SET_BUTTON, MainForm::OnRemoveSetButtonClick )

	EVT_BUTTON( ID_CLEAR_SET_BUTTON, MainForm::OnClearSetButtonClick )

	EVT_BUTTON( ID_RESET_SET_RESULTS_BUTTON, MainForm::OnResetSetResultsButtonClick )

	EVT_LIST_ITEM_SELECTED( ID_SETS_LISTVIEW, MainForm::OnSetsListviewSelected )
	EVT_LIST_ITEM_DESELECTED( ID_SETS_LISTVIEW, MainForm::OnSetsListviewDeselected )
	EVT_LIST_END_LABEL_EDIT( ID_SETS_LISTVIEW, MainForm::OnSetsListviewEndLabelEdit )

	EVT_BUTTON( ID_ADD_SAMPLES_BUTTON, MainForm::OnAddSamplesButtonClick )

	EVT_BUTTON( ID_REMOVE_SAMPLES_BUTTON, MainForm::OnRemoveSamplesButtonClick )

	EVT_BUTTON( ID_CLEAR_SAMPLES_BUTTON, MainForm::OnClearSamplesButtonClick )

	EVT_TEXT( ID_CLASS_SAMPLES_TEXTCTRL, MainForm::OnClassSamplesTextctrlUpdated )

	EVT_CHECKBOX( ID_DISPLAY_CHECKBOX, MainForm::OnDisplayCheckboxClick )

	EVT_SPINCTRL( ID_DISP_BUF_SPINCTRL, MainForm::OnDispBufSpinctrlUpdated )

	EVT_TOGGLEBUTTON( ID_PROCESS_TOGGLEBUTTON, MainForm::OnProcessTogglebuttonClick )

////@end MainForm event table entries

END_EVENT_TABLE()

/*!
 * MainForm constructors
 */

MainForm::MainForm( )
{
	Init();
}

MainForm::MainForm( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
	Init();
	Create( parent, id, caption, pos, size, style );
}

/*!
 * MainForm creator
 */

bool MainForm::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
////@begin MainForm creation
	wxFrame::Create( parent, id, caption, pos, size, style );

	CreateControls();
	SetIcon(GetIconResource(wxT("src/SCANN_icon.xpm")));
	Centre();
////@end MainForm creation

	// Disable samples panel
	this->samplesPanel->Enable(false);

	// Set the display buffer size control
	this->dspBufSpinCtrl->SetValue(DEFAULT_DSP_BUF_SIZE);

	// List controls
	this->setsListView->InsertColumn	(0,	"Set",		wxLIST_FORMAT_LEFT,	65	);
	this->setsListView->InsertColumn	(1,	"Average",	wxLIST_FORMAT_LEFT,	68	);
	this->setsListView->InsertColumn	(2,	"Std Dev",	wxLIST_FORMAT_LEFT,	68	);
	this->samplesListView->InsertColumn	(0,	"Sample",	wxLIST_FORMAT_LEFT,	140	);
	this->samplesListView->InsertColumn	(1,	"Outputs",	wxLIST_FORMAT_LEFT,	60	);

	// Initialise plot
	this->setPlot->SetZoom(.45);

	// Initialise systems visualisation frame
	this->displayFrame->SetEngine(&this->engine);

	// Create systems text display dialog
	this->systems_dialog = new SystemsDialog(this, ID_SYSTEMS_DIALOG, _("Systems"));

	// Set engine recording level to 1
	this->engine.SetRecordingLevel(1);

	return true;
}

/*!
 * MainForm destructor
 */

MainForm::~MainForm()
{
////@begin MainForm destruction
////@end MainForm destruction
}

/*!
 * Member initialisation 
 */

void MainForm::Init()
{
////@begin MainForm member initialisation
	sysColourList = NULL;
	plugin_dirs = vector<string>(1,"plugins");
	systems_dialog = NULL;
	current_sample = NO_SAMPLE;
	fileMenu = NULL;
	mainSplitter = NULL;
	progNameLabel = NULL;
	loadButton = NULL;
	nbSysLabel = NULL;
	nbCtxLabel = NULL;
	displayFrame = NULL;
	runToggleButton = NULL;
	resetButton = NULL;
	showSystemsButton = NULL;
	addSetsButton = NULL;
	removeSetsButton = NULL;
	clearSetsButton = NULL;
	setsType = NULL;
	setsSize = NULL;
	setsListView = NULL;
	samplesPanel = NULL;
	addSamplesButton = NULL;
	removeSamplesButton = NULL;
	clearSamplesButton = NULL;
	samplesNumber = NULL;
	samplesClassification = NULL;
	samplesListView = NULL;
	setPlot = NULL;
	ipsSpinCtrl = NULL;
	learnSpikeSpinCtrl = NULL;
	displayCheckBox = NULL;
	dspBufSpinCtrl = NULL;
	epochNbLabel = NULL;
	sampleNbLabel = NULL;
	curSetLabel = NULL;
	curInputLabel = NULL;
	processToggleButton = NULL;
	maxSupEpochsSpinCtrl = NULL;
	batchRadioButton = NULL;
	learningStateLabel = NULL;
////@end MainForm member initialisation
}
/*!
 * Control creation for MainForm
 */

void MainForm::CreateControls()
{    
////@begin MainForm content construction
	MainForm* itemFrame1 = this;

	wxMenuBar* menuBar = new wxMenuBar;
	fileMenu = new wxMenu;
	{
		wxMenuItem* menuItem = new wxMenuItem(fileMenu, ID_LOAD_PROGRAM_MENUITEM, _("Load Program"), _T(""), wxITEM_NORMAL);
		wxBitmap bitmap(itemFrame1->GetBitmapResource(wxT("src/open.xpm")));
		menuItem->SetBitmap(bitmap);
		fileMenu->Append(menuItem);
	}
	fileMenu->AppendSeparator();
	{
		wxMenuItem* menuItem = new wxMenuItem(fileMenu, ID_LOAD_DATA_MENUITEM, _("Load Data Setup"), _T(""), wxITEM_NORMAL);
		wxBitmap bitmap(itemFrame1->GetBitmapResource(wxT("src/load_from.xpm")));
		menuItem->SetBitmap(bitmap);
		fileMenu->Append(menuItem);
	}
	{
		wxMenuItem* menuItem = new wxMenuItem(fileMenu, ID_SAVE_DATA_MENUITEM, _("Save Data Setup"), _T(""), wxITEM_NORMAL);
		wxBitmap bitmap(itemFrame1->GetBitmapResource(wxT("src/save_to.xpm")));
		menuItem->SetBitmap(bitmap);
		fileMenu->Append(menuItem);
	}
	fileMenu->AppendSeparator();
	{
		wxMenuItem* menuItem = new wxMenuItem(fileMenu, ID_EXPORT_RESULTS_MENUITEM, _("Export Results"), _T(""), wxITEM_NORMAL);
		wxBitmap bitmap(itemFrame1->GetBitmapResource(wxT("src/forward.xpm")));
		menuItem->SetBitmap(bitmap);
		fileMenu->Append(menuItem);
	}
	fileMenu->AppendSeparator();
	{
		wxMenuItem* menuItem = new wxMenuItem(fileMenu, ID_QUIT_MENUITEM, _("Quit"), _T(""), wxITEM_NORMAL);
		wxBitmap bitmap(itemFrame1->GetBitmapResource(wxT("src/exit.xpm")));
		menuItem->SetBitmap(bitmap);
		fileMenu->Append(menuItem);
	}
	menuBar->Append(fileMenu, _("File"));
	wxMenu* itemMenu12 = new wxMenu;
	{
		wxMenuItem* menuItem = new wxMenuItem(itemMenu12, ID_PLUGIN_DIR_MENUITEM, _("Plug-in directories"), _T(""), wxITEM_NORMAL);
		wxBitmap bitmap(itemFrame1->GetBitmapResource(wxT("src/plugin_dir.xpm")));
		menuItem->SetBitmap(bitmap);
		itemMenu12->Append(menuItem);
	}
	menuBar->Append(itemMenu12, _("Config"));
	wxMenu* itemMenu14 = new wxMenu;
	{
		wxMenuItem* menuItem = new wxMenuItem(itemMenu14, wxID_ABOUT, _("About"), _T(""), wxITEM_NORMAL);
		wxBitmap bitmap(itemFrame1->GetBitmapResource(wxT("src/help.xpm")));
		menuItem->SetBitmap(bitmap);
		itemMenu14->Append(menuItem);
	}
	menuBar->Append(itemMenu14, _("Help"));
	itemFrame1->SetMenuBar(menuBar);

	mainSplitter = new wxSplitterWindow( itemFrame1, ID_MAIN_SPLITTERWINDOW, wxDefaultPosition, wxSize(100, 100), wxNO_BORDER );
	mainSplitter->SetMinimumPaneSize(1);
	mainSplitter->SetSashGravity(0.3);

	wxPanel* itemPanel17 = new wxPanel( mainSplitter, ID_LEFT_PANEL, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
	wxBoxSizer* itemBoxSizer18 = new wxBoxSizer(wxVERTICAL);
	itemPanel17->SetSizer(itemBoxSizer18);

	wxStaticBox* itemStaticBoxSizer19Static = new wxStaticBox(itemPanel17, wxID_ANY, _("Program"));
	wxStaticBoxSizer* itemStaticBoxSizer19 = new wxStaticBoxSizer(itemStaticBoxSizer19Static, wxVERTICAL);
	itemBoxSizer18->Add(itemStaticBoxSizer19, 0, wxGROW|wxALL, 5);
	wxBoxSizer* itemBoxSizer20 = new wxBoxSizer(wxHORIZONTAL);
	itemStaticBoxSizer19->Add(itemBoxSizer20, 0, wxGROW|wxALL, 5);
	wxStaticText* itemStaticText21 = new wxStaticText( itemPanel17, wxID_STATIC, _("Name"), wxDefaultPosition, wxSize(50, -1), 0 );
	itemBoxSizer20->Add(itemStaticText21, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	progNameLabel = new wxStaticText( itemPanel17, wxID_STATIC, _T(""), wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE );
	itemBoxSizer20->Add(progNameLabel, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	loadButton = new wxButton( itemPanel17, ID_LOAD_PROGRAM_BUTTON, _("Load"), wxDefaultPosition, wxDefaultSize, 0 );
	itemBoxSizer20->Add(loadButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10);

	wxBoxSizer* itemBoxSizer24 = new wxBoxSizer(wxHORIZONTAL);
	itemStaticBoxSizer19->Add(itemBoxSizer24, 0, wxGROW|wxALL, 5);
	wxStaticText* itemStaticText25 = new wxStaticText( itemPanel17, wxID_STATIC, _("Systems"), wxDefaultPosition, wxSize(50, -1), 0 );
	itemBoxSizer24->Add(itemStaticText25, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	nbSysLabel = new wxStaticText( itemPanel17, wxID_STATIC, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
	nbSysLabel->SetForegroundColour(wxColour(92, 92, 92));
	itemBoxSizer24->Add(nbSysLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxStaticText* itemStaticText27 = new wxStaticText( itemPanel17, wxID_STATIC, _("Contexts"), wxDefaultPosition, wxSize(50, -1), 0 );
	itemBoxSizer24->Add(itemStaticText27, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	nbCtxLabel = new wxStaticText( itemPanel17, wxID_STATIC, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
	nbCtxLabel->SetForegroundColour(wxColour(92, 92, 92));
	itemBoxSizer24->Add(nbCtxLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	displayFrame = new SCDisplayFrame( itemPanel17, ID_SCDISPLAYFRAME, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER );
	itemBoxSizer18->Add(displayFrame, 1, wxGROW|wxALL, 5);

	wxStaticBox* itemStaticBoxSizer30Static = new wxStaticBox(itemPanel17, wxID_ANY, _("Simulation"));
	wxStaticBoxSizer* itemStaticBoxSizer30 = new wxStaticBoxSizer(itemStaticBoxSizer30Static, wxHORIZONTAL);
	itemBoxSizer18->Add(itemStaticBoxSizer30, 0, wxGROW|wxALL, 5);
	runToggleButton = new wxToggleButton( itemPanel17, ID_RUN_TOGGLEBUTTON, _("Run"), wxDefaultPosition, wxDefaultSize, 0 );
	runToggleButton->SetValue(false);
	runToggleButton->Enable(false);
	itemStaticBoxSizer30->Add(runToggleButton, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	resetButton = new wxButton( itemPanel17, ID_RESET_BUTTON, _("Reset"), wxDefaultPosition, wxDefaultSize, 0 );
	resetButton->Enable(false);
	itemStaticBoxSizer30->Add(resetButton, 1, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5);

	showSystemsButton = new wxButton( itemPanel17, ID_SHOW_SYSTEMS_BUTTON, _("Show Systems"), wxDefaultPosition, wxDefaultSize, 0 );
	showSystemsButton->Enable(false);
	itemStaticBoxSizer30->Add(showSystemsButton, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxPanel* itemPanel34 = new wxPanel( mainSplitter, ID_RIGHT_PANEL, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
	wxStaticBox* itemStaticBoxSizer35Static = new wxStaticBox(itemPanel34, wxID_ANY, _("Data"));
	wxStaticBoxSizer* itemStaticBoxSizer35 = new wxStaticBoxSizer(itemStaticBoxSizer35Static, wxVERTICAL);
	itemPanel34->SetSizer(itemStaticBoxSizer35);

	wxBoxSizer* itemBoxSizer36 = new wxBoxSizer(wxHORIZONTAL);
	itemStaticBoxSizer35->Add(itemBoxSizer36, 1, wxGROW|wxALL, 0);
	wxStaticBox* itemStaticBoxSizer37Static = new wxStaticBox(itemPanel34, wxID_ANY, _("Sets"));
	wxStaticBoxSizer* itemStaticBoxSizer37 = new wxStaticBoxSizer(itemStaticBoxSizer37Static, wxVERTICAL);
	itemStaticBoxSizer37Static->Enable(false);
	itemBoxSizer36->Add(itemStaticBoxSizer37, 1, wxGROW|wxALL, 5);
	wxBoxSizer* itemBoxSizer38 = new wxBoxSizer(wxHORIZONTAL);
	itemStaticBoxSizer37->Add(itemBoxSizer38, 1, wxGROW|wxRIGHT|wxTOP|wxBOTTOM, 0);
	wxBoxSizer* itemBoxSizer39 = new wxBoxSizer(wxVERTICAL);
	itemBoxSizer38->Add(itemBoxSizer39, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);
	addSetsButton = new wxButton( itemPanel34, ID_ADD_SET_BUTTON, _("Add"), wxDefaultPosition, wxSize(-1, 20), 0 );
	itemBoxSizer39->Add(addSetsButton, 0, wxALIGN_CENTER_HORIZONTAL, 5);

	removeSetsButton = new wxButton( itemPanel34, ID_REMOVE_SET_BUTTON, _("Remove"), wxDefaultPosition, wxSize(-1, 20), 0 );
	itemBoxSizer39->Add(removeSetsButton, 0, wxALIGN_CENTER_HORIZONTAL, 5);

	clearSetsButton = new wxButton( itemPanel34, ID_CLEAR_SET_BUTTON, _("Clear"), wxDefaultPosition, wxSize(-1, 20), 0 );
	itemBoxSizer39->Add(clearSetsButton, 0, wxALIGN_CENTER_HORIZONTAL, 5);

	wxBoxSizer* itemBoxSizer43 = new wxBoxSizer(wxHORIZONTAL);
	itemBoxSizer39->Add(itemBoxSizer43, 0, wxGROW, 5);
	wxStaticText* itemStaticText44 = new wxStaticText( itemPanel34, wxID_STATIC, _("Type"), wxDefaultPosition, wxDefaultSize, 0 );
	itemBoxSizer43->Add(itemStaticText44, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	setsType = new wxStaticText( itemPanel34, wxID_STATIC, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
	setsType->SetForegroundColour(wxColour(92, 92, 92));
	itemBoxSizer43->Add(setsType, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxBoxSizer* itemBoxSizer46 = new wxBoxSizer(wxHORIZONTAL);
	itemBoxSizer39->Add(itemBoxSizer46, 0, wxGROW|wxLEFT, 5);
	wxStaticText* itemStaticText47 = new wxStaticText( itemPanel34, wxID_STATIC, _("Size"), wxDefaultPosition, wxDefaultSize, 0 );
	itemBoxSizer46->Add(itemStaticText47, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	setsSize = new wxStaticText( itemPanel34, wxID_STATIC, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
	setsSize->SetForegroundColour(wxColour(92, 92, 92));
	itemBoxSizer46->Add(setsSize, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxButton* itemButton49 = new wxButton( itemPanel34, ID_RESET_SET_RESULTS_BUTTON, _("Reset"), wxDefaultPosition, wxSize(-1, 20), 0 );
	itemBoxSizer39->Add(itemButton49, 0, wxALIGN_CENTER_HORIZONTAL, 5);

	setsListView = new wxListView( itemPanel34, ID_SETS_LISTVIEW, wxDefaultPosition, wxSize(100, 100), wxLC_REPORT|wxLC_EDIT_LABELS|wxLC_SINGLE_SEL );
	itemBoxSizer38->Add(setsListView, 1, wxGROW|wxLEFT, 5);

	wxStaticBox* itemStaticBoxSizer51Static = new wxStaticBox(itemPanel34, wxID_ANY, _("Set Samples"));
	wxStaticBoxSizer* itemStaticBoxSizer51 = new wxStaticBoxSizer(itemStaticBoxSizer51Static, wxVERTICAL);
	itemBoxSizer36->Add(itemStaticBoxSizer51, 1, wxGROW|wxALL, 5);
	samplesPanel = new wxPanel( itemPanel34, ID_SAMPLES_PANEL, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
	itemStaticBoxSizer51->Add(samplesPanel, 1, wxGROW|wxALL, 0);
	wxBoxSizer* itemBoxSizer53 = new wxBoxSizer(wxHORIZONTAL);
	samplesPanel->SetSizer(itemBoxSizer53);

	wxBoxSizer* itemBoxSizer54 = new wxBoxSizer(wxVERTICAL);
	itemBoxSizer53->Add(itemBoxSizer54, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);
	addSamplesButton = new wxButton( samplesPanel, ID_ADD_SAMPLES_BUTTON, _("Add"), wxDefaultPosition, wxSize(-1, 20), 0 );
	itemBoxSizer54->Add(addSamplesButton, 0, wxALIGN_CENTER_HORIZONTAL, 5);

	removeSamplesButton = new wxButton( samplesPanel, ID_REMOVE_SAMPLES_BUTTON, _("Remove"), wxDefaultPosition, wxSize(-1, 20), 0 );
	itemBoxSizer54->Add(removeSamplesButton, 0, wxALIGN_CENTER_HORIZONTAL, 5);

	clearSamplesButton = new wxButton( samplesPanel, ID_CLEAR_SAMPLES_BUTTON, _("Clear"), wxDefaultPosition, wxSize(-1, 20), 0 );
	itemBoxSizer54->Add(clearSamplesButton, 0, wxALIGN_CENTER_HORIZONTAL, 5);

	wxBoxSizer* itemBoxSizer58 = new wxBoxSizer(wxHORIZONTAL);
	itemBoxSizer54->Add(itemBoxSizer58, 0, wxGROW, 5);
	wxStaticText* itemStaticText59 = new wxStaticText( samplesPanel, wxID_STATIC, _("Number"), wxDefaultPosition, wxDefaultSize, 0 );
	itemBoxSizer58->Add(itemStaticText59, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	samplesNumber = new wxStaticText( samplesPanel, wxID_STATIC, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
	samplesNumber->SetForegroundColour(wxColour(92, 92, 92));
	itemBoxSizer58->Add(samplesNumber, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxBoxSizer* itemBoxSizer61 = new wxBoxSizer(wxHORIZONTAL);
	itemBoxSizer54->Add(itemBoxSizer61, 0, wxGROW, 5);
	wxStaticText* itemStaticText62 = new wxStaticText( samplesPanel, wxID_STATIC, _("Class"), wxDefaultPosition, wxDefaultSize, 0 );
	itemBoxSizer61->Add(itemStaticText62, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP|wxBOTTOM, 5);

	samplesClassification = new wxTextCtrl( samplesPanel, ID_CLASS_SAMPLES_TEXTCTRL, _T(""), wxDefaultPosition, wxSize(25, -1), 0 );
	itemBoxSizer61->Add(samplesClassification, 1, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5);

	samplesListView = new wxListView( samplesPanel, ID_SAMPLES_LISTVIEW, wxDefaultPosition, wxSize(100, 100), wxLC_REPORT );
	itemBoxSizer53->Add(samplesListView, 1, wxGROW|wxLEFT, 5);

	setPlot = new wxPlotWindow( itemPanel34, ID_PLOTWINDOW, wxDefaultPosition, wxSize(-1, 150), wxSIMPLE_BORDER | wxPLOT_DEFAULT );
	itemStaticBoxSizer35->Add(setPlot, 0, wxGROW|wxALL, 2);

	wxBoxSizer* itemBoxSizer66 = new wxBoxSizer(wxHORIZONTAL);
	itemStaticBoxSizer35->Add(itemBoxSizer66, 0, wxGROW|wxTOP, 5);
	wxStaticBox* itemStaticBoxSizer67Static = new wxStaticBox(itemPanel34, wxID_ANY, _("Time setup"));
	wxStaticBoxSizer* itemStaticBoxSizer67 = new wxStaticBoxSizer(itemStaticBoxSizer67Static, wxHORIZONTAL);
	itemBoxSizer66->Add(itemStaticBoxSizer67, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5);
	wxStaticText* itemStaticText68 = new wxStaticText( itemPanel34, wxID_STATIC, _("Iterations per sample"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer67->Add(itemStaticText68, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	ipsSpinCtrl = new wxSpinCtrl( itemPanel34, ID_IPS_SPINCTRL, _T("100"), wxDefaultPosition, wxSize(60, -1), wxSP_ARROW_KEYS, 1, 2147483647, 100 );
	itemStaticBoxSizer67->Add(ipsSpinCtrl, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5);

	wxStaticText* itemStaticText70 = new wxStaticText( itemPanel34, wxID_STATIC, _("Learning spike"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer67->Add(itemStaticText70, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	learnSpikeSpinCtrl = new wxSpinCtrl( itemPanel34, ID_LEARN_SPIKE_SPINCTRL, _T("50"), wxDefaultPosition, wxSize(60, -1), wxSP_ARROW_KEYS, 0, 2147483647, 50 );
	itemStaticBoxSizer67->Add(learnSpikeSpinCtrl, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5);

	wxStaticBox* itemStaticBoxSizer72Static = new wxStaticBox(itemPanel34, wxID_ANY, _("Display setup"));
	wxStaticBoxSizer* itemStaticBoxSizer72 = new wxStaticBoxSizer(itemStaticBoxSizer72Static, wxHORIZONTAL);
	itemBoxSizer66->Add(itemStaticBoxSizer72, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5);
	displayCheckBox = new wxCheckBox( itemPanel34, ID_DISPLAY_CHECKBOX, _("Update display"), wxDefaultPosition, wxDefaultSize, 0 );
	displayCheckBox->SetValue(true);
	itemStaticBoxSizer72->Add(displayCheckBox, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxStaticText* itemStaticText74 = new wxStaticText( itemPanel34, wxID_STATIC, _("Display buffer"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer72->Add(itemStaticText74, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	dspBufSpinCtrl = new wxSpinCtrl( itemPanel34, ID_DISP_BUF_SPINCTRL, _T("1000"), wxDefaultPosition, wxSize(60, -1), wxSP_ARROW_KEYS, 1, 2147483647, 1000 );
	itemStaticBoxSizer72->Add(dspBufSpinCtrl, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5);

	wxStaticBox* itemStaticBoxSizer76Static = new wxStaticBox(itemPanel34, wxID_ANY, _("Current state"));
	wxStaticBoxSizer* itemStaticBoxSizer76 = new wxStaticBoxSizer(itemStaticBoxSizer76Static, wxHORIZONTAL);
	itemStaticBoxSizer35->Add(itemStaticBoxSizer76, 0, wxGROW|wxALL, 5);
	wxStaticText* itemStaticText77 = new wxStaticText( itemPanel34, wxID_STATIC, _("Epoch"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer76->Add(itemStaticText77, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	epochNbLabel = new wxStaticText( itemPanel34, wxID_STATIC, _("0"), wxDefaultPosition, wxSize(35, -1), 0 );
	epochNbLabel->SetForegroundColour(wxColour(92, 92, 92));
	itemStaticBoxSizer76->Add(epochNbLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxStaticText* itemStaticText79 = new wxStaticText( itemPanel34, wxID_STATIC, _("Sample"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer76->Add(itemStaticText79, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	sampleNbLabel = new wxStaticText( itemPanel34, wxID_STATIC, _("0"), wxDefaultPosition, wxSize(35, -1), 0 );
	sampleNbLabel->SetForegroundColour(wxColour(92, 92, 92));
	itemStaticBoxSizer76->Add(sampleNbLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxStaticText* itemStaticText81 = new wxStaticText( itemPanel34, wxID_STATIC, _("Set"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer76->Add(itemStaticText81, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	curSetLabel = new wxStaticText( itemPanel34, wxID_STATIC, _T(""), wxDefaultPosition, wxSize(70, -1), 0 );
	curSetLabel->SetForegroundColour(wxColour(92, 92, 92));
	itemStaticBoxSizer76->Add(curSetLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxStaticText* itemStaticText83 = new wxStaticText( itemPanel34, wxID_STATIC, _("Input"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer76->Add(itemStaticText83, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	curInputLabel = new wxStaticText( itemPanel34, wxID_STATIC, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
	curInputLabel->SetForegroundColour(wxColour(92, 92, 92));
	itemStaticBoxSizer76->Add(curInputLabel, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxBoxSizer* itemBoxSizer85 = new wxBoxSizer(wxHORIZONTAL);
	itemStaticBoxSizer35->Add(itemBoxSizer85, 0, wxGROW|wxALL, 0);
	processToggleButton = new wxToggleButton( itemPanel34, ID_PROCESS_TOGGLEBUTTON, _("Process"), wxDefaultPosition, wxDefaultSize, 0 );
	processToggleButton->SetValue(false);
	processToggleButton->Enable(false);
	itemBoxSizer85->Add(processToggleButton, 1, wxALIGN_CENTER_VERTICAL|wxALL, 0);

	wxStaticBox* itemStaticBoxSizer87Static = new wxStaticBox(itemPanel34, wxID_ANY, _("Supervision"));
	wxStaticBoxSizer* itemStaticBoxSizer87 = new wxStaticBoxSizer(itemStaticBoxSizer87Static, wxHORIZONTAL);
	itemBoxSizer85->Add(itemStaticBoxSizer87, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5);
	wxStaticText* itemStaticText88 = new wxStaticText( itemPanel34, wxID_STATIC, _("Supervise for"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer87->Add(itemStaticText88, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	maxSupEpochsSpinCtrl = new wxSpinCtrl( itemPanel34, ID_MAX_EPOCHS_SPINCTRL, _T("50"), wxDefaultPosition, wxSize(60, -1), wxSP_ARROW_KEYS, 0, 2147483647, 50 );
	itemStaticBoxSizer87->Add(maxSupEpochsSpinCtrl, 0, wxALIGN_CENTER_VERTICAL, 5);

	wxStaticText* itemStaticText90 = new wxStaticText( itemPanel34, wxID_STATIC, _("epochs"), wxDefaultPosition, wxDefaultSize, 0 );
	itemStaticBoxSizer87->Add(itemStaticText90, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	batchRadioButton = new wxRadioButton( itemPanel34, ID_BATCH_RADIOBUTTON, _("Batch"), wxDefaultPosition, wxDefaultSize, 0 );
	batchRadioButton->SetValue(false);
	itemStaticBoxSizer87->Add(batchRadioButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	wxRadioButton* itemRadioButton92 = new wxRadioButton( itemPanel34, ID_ONLINE_RADIOBUTTON, _("On-line"), wxDefaultPosition, wxDefaultSize, 0 );
	itemRadioButton92->SetValue(true);
	itemStaticBoxSizer87->Add(itemRadioButton92, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	learningStateLabel = new wxStaticText( itemPanel34, wxID_STATIC, _("..."), wxDefaultPosition, wxSize(60, -1), wxALIGN_CENTRE );
	learningStateLabel->SetForegroundColour(wxColour(92, 92, 92));
	itemStaticBoxSizer87->Add(learningStateLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

	mainSplitter->SplitVertically(itemPanel17, itemPanel34, 400);

////@end MainForm content construction
}

/*!
 * Should we show tooltips?
 */

bool MainForm::ShowToolTips()
{
	return true;
}

/*!
 * Get bitmap resources
 */

wxBitmap MainForm::GetBitmapResource( const wxString& name )
{
	// Bitmap retrieval
////@begin MainForm bitmap retrieval
	wxUnusedVar(name);
	if (name == _T("src/open.xpm"))
	{
		wxBitmap bitmap( open_xpm);
		return bitmap;
	}
	else if (name == _T("src/load_from.xpm"))
	{
		wxBitmap bitmap( load_from_xpm);
		return bitmap;
	}
	else if (name == _T("src/save_to.xpm"))
	{
		wxBitmap bitmap( save_to_xpm);
		return bitmap;
	}
	else if (name == _T("src/forward.xpm"))
	{
		wxBitmap bitmap( forward_xpm);
		return bitmap;
	}
	else if (name == _T("src/exit.xpm"))
	{
		wxBitmap bitmap( exit_xpm);
		return bitmap;
	}
	else if (name == _T("src/plugin_dir.xpm"))
	{
		wxBitmap bitmap( plugin_dir_xpm);
		return bitmap;
	}
	else if (name == _T("src/help.xpm"))
	{
		wxBitmap bitmap( help_xpm);
		return bitmap;
	}
	return wxNullBitmap;
////@end MainForm bitmap retrieval
}

/*!
 * Get icon resources
 */

wxIcon MainForm::GetIconResource( const wxString& name )
{
	// Icon retrieval
////@begin MainForm icon retrieval
	wxUnusedVar(name);
	if (name == _T("src/SCANN_icon.xpm"))
	{
		wxIcon icon( SCANN_icon_xpm);
		return icon;
	}
	return wxNullIcon;
////@end MainForm icon retrieval
}

/*!
 * wxEVT_SIZE event handler for ID_MAINFORM
 */

void MainForm::OnSize( wxSizeEvent& event )
{
	try {
		if (this->displayFrame != NULL) this->displayFrame->Refresh(false);
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_SIZE event handler for ID_MAINFORM in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_SIZE event handler for ID_MAINFORM in MainForm. 
}

/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_LOAD_PROGRAM_MENUITEM
 */

void MainForm::OnLoadProgramMenuitemClick( wxCommandEvent& event )
{
	this->loadProgram();
////@begin wxEVT_COMMAND_MENU_SELECTED event handler for ID_LOAD_PROGRAM_MENUITEM in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_MENU_SELECTED event handler for ID_LOAD_PROGRAM_MENUITEM in MainForm. 
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_LOAD_DATA_MENUITEM
 */

void MainForm::OnLoadDataMenuitemClick( wxCommandEvent& event )
{
	wxString path = wxFileSelector("Load data setup file","setup","","dsu","Data Setup files (*.dsu)|*.dsu|All files (*.*)|*.*",wxOPEN,this);
	if (!path.empty()) {
		ifstream file(path.c_str());
		try {
			// Check file is open
			if (!file.is_open())
				throw IOFileException("Data setup file \"" + string(path.c_str()) + "\" doesn't exist");
			// Reset
			wxCommandEvent evt; OnClearSetButtonClick(evt);
			// Read sets
			unsigned int nb_sets;
			file >> nb_sets;
			for (unsigned int i=0; i<nb_sets; ++i)
				this->sets.push_back(SampleSet(file));
			// Add sets in list view
			wxListItem item;
			for (unsigned int i=0; i<this->sets.size(); ++i) {
				item.SetId(i);
				item.SetColumn(0);
				item.SetText(_(this->sets[i].GetName().c_str()));
				this->setsListView->InsertItem(item);
				item.SetColumn(1);
				item.SetText("");
				this->setsListView->SetItem(item);
				item.SetColumn(2);
				item.SetText("");
				this->setsListView->SetItem(item);
			}
			if (!this->sets.empty()) {
				this->setsType->SetLabel(_(this->sets[0].GetSamples().GetDataType().c_str()));
				this->setsSize->SetLabel(wxString::Format("%d",this->sets[0].GetSamples().GetDataSize()));
			}
			// Reset variables and fields
			this->resetVariables();
			this->resetFields();
			// Eventually enable process button
			this->updateProcessButton();
		}
		catch (exception & e) {
			// Close file
			if (file.is_open())	file.close();
			wxMessageBox(_(e.what()));
		}
	}
////@begin wxEVT_COMMAND_MENU_SELECTED event handler for ID_LOAD_DATA_MENUITEM in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_MENU_SELECTED event handler for ID_LOAD_DATA_MENUITEM in MainForm. 
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_SAVE_DATA_MENUITEM
 */

void MainForm::OnSaveDataMenuitemClick( wxCommandEvent& event )
{
	wxString path = wxFileSelector("Save data setup to file","setup","","dsu","Data Setup files (*.dsu)|*.dsu|All files (*.*)|*.*",wxSAVE,this);
	if (!path.empty()) {
		ofstream file(path.c_str());
		try {
			// Check file is open
			if (!file.is_open())
				throw IOFileException("Data setup file \"" + string(path.c_str()) + "\" doesn't exist");
			// Write sets
			file << this->sets.size() << endl;
			for (unsigned int i=0; i<this->sets.size(); ++i) {
				file << endl;
				this->sets[i].Write(file);
			}
		}
		catch (exception & e) {
			// Close file
			if (file.is_open())	file.close();
			wxMessageBox(_(e.what()));
		}
	}
////@begin wxEVT_COMMAND_MENU_SELECTED event handler for ID_SAVE_DATA_MENUITEM in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_MENU_SELECTED event handler for ID_SAVE_DATA_MENUITEM in MainForm. 
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_EXPORT_RESULTS_MENUITEM
 */

void MainForm::OnExportResultsMenuitemClick( wxCommandEvent& event )
{
	wxString path = wxFileSelector("Export results to file","results","","res","Data Results files (*.res)|*.res|All files (*.*)|*.*",wxSAVE,this);
	if (!path.empty()) {
		ofstream file(path.c_str());
		try {
			// Check file is open
			if (!file.is_open())
				throw IOFileException("Data setup file \"" + string(path.c_str()) + "\" doesn't exist");
			// Export results
			//file << "Nb Sets " << this->sets.size() << endl << endl;
			for (unsigned int i=0; i<this->sets.size(); ++i) {
				this->sets[i].ExportResults(file);
				file << endl;
			}
		}
		catch (exception & e) {
			// Close file
			if (file.is_open())	file.close();
			wxMessageBox(_(e.what()));
		}
	}
////@begin wxEVT_COMMAND_MENU_SELECTED event handler for ID_EXPORT_RESULTS_MENUITEM in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_MENU_SELECTED event handler for ID_EXPORT_RESULTS_MENUITEM in MainForm. 
}

/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_QUIT_MENUITEM
 */

void MainForm::OnQuitMenuitemClick( wxCommandEvent& event )
{
////@begin wxEVT_COMMAND_MENU_SELECTED event handler for ID_QUIT_MENUITEM in MainForm.
	// Before editing this code, remove the block markers.
	Destroy();
////@end wxEVT_COMMAND_MENU_SELECTED event handler for ID_QUIT_MENUITEM in MainForm. 
}

/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_PLUGIN_DIR_MENUITEM
 */

void MainForm::OnPluginDirMenuitemClick( wxCommandEvent& event )
{
	try {
		wxString dirs;
		for (unsigned int i=0; i<this->plugin_dirs.size(); ++i) {
			dirs += this->plugin_dirs[i].c_str();
			if (i != this->plugin_dirs.size()-1) dirs += ';';
		}
		wxTextEntryDialog dialog(this, "Directories", "Plug-in directories setup" , dirs);
		if (dialog.ShowModal() == wxID_OK) {
			dirs = dialog.GetValue().Trim();
			while (dirs[0] == ';') dirs.Remove(0,1);
			if (!dirs.IsEmpty()) {
				this->plugin_dirs.clear();
				while (dirs.Length() > 0) {
					int idx = dirs.First(';');
					if (idx == -1) idx = dirs.Length();
					this->plugin_dirs.push_back(string(dirs.SubString(0,idx-1).c_str()));
					dirs.Remove(0,idx);
					while (dirs[0] == ';') dirs.Remove(0,1);
				}
			}
		}
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_MENU_SELECTED event handler for ID_PLUGIN_DIR_MENUITEM in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_MENU_SELECTED event handler for ID_PLUGIN_DIR_MENUITEM in MainForm. 
}

/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for wxID_ABOUT
 */

void MainForm::OnAboutClick( wxCommandEvent& event )
{
	wxAboutDialogInfo info;
    info.SetName(_("SCANN"));
    info.SetVersion(_(STRING_VERSION));
    info.SetDescription(_("Systemic Computation Artificial Neural Networks Environment"));
    info.SetCopyright(_T("(C) 2006-2009 Erwan Le Martelot <e.le_martelot@ucl.ac.uk>"));
	info.SetIcon(wxIcon(SCANN_xpm));
	info.SetWebSite(_("http://www.cs.ucl.ac.uk/staff/E.LeMartelot"));
	wxArrayString developers; developers.Add(_("Erwan Le Martelot\nUniversity College London, London, UK\ne.le_martelot@ucl.ac.uk\nhttp://www.cs.ucl.ac.uk/staff/E.LeMartelot"));
	info.SetDevelopers(developers);
	info.SetLicense(_("GNU General Public License\nhttp://www.gnu.org/licenses/gpl.html"));
	wxAboutBox(info);
////@begin wxEVT_COMMAND_MENU_SELECTED event handler for wxID_ABOUT in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_MENU_SELECTED event handler for wxID_ABOUT in MainForm. 
}

/*!
 * wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED event handler for ID_MAIN_SPLITTERWINDOW
 */

void MainForm::OnMainSplitterwindowSashPosChanged( wxSplitterEvent& event )
{
	try {
		this->displayFrame->Refresh(false);
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED event handler for ID_MAIN_SPLITTERWINDOW in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED event handler for ID_MAIN_SPLITTERWINDOW in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_LOAD_PROGRAMME_BUTTON
 */

void MainForm::OnLoadProgramButtonClick( wxCommandEvent& event )
{
	this->loadProgram();
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_LOAD_PROGRAMME_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_LOAD_PROGRAMME_BUTTON in MainForm. 
}

void MainForm::loadProgram() {
	wxString path = wxFileSelector("Load binary file","bin","","bsc","SC Binary files (*.bsc)|*.bsc|All files (*.*)|*.*",wxOPEN,this);
	if (!path.empty()) {
		try {
			// Read program
			this->program.ReadByteCode(string(path.c_str()));
			// Load data
			this->engine.InitData(this->program,this->plugin_dirs);
			// Initialise fields
			wxFileName filename(path);
			this->progNameLabel->SetLabel(filename.GetName());
			this->nbSysLabel->SetLabel(wxString::Format("%d",this->engine.GetNbSystems()));
			this->nbCtxLabel->SetLabel(wxString::Format("%d",this->engine.GetContexts().size()));
			this->resetButton->Enable(true);
			this->runToggleButton->Enable(true);
			this->showSystemsButton->Enable(true);
			this->systems_dialog->SetData(this->program,this->engine.GetSystems());
		}
		catch(exception & e) {
			this->program.Clear();
			this->engine.Clear();
			this->progNameLabel->SetLabel("");
			this->nbSysLabel->SetLabel("");
			this->nbCtxLabel->SetLabel("");
			this->resetButton->Enable(false);
			this->runToggleButton->SetValue(false);
			this->runToggleButton->Enable(false);
			this->systems_dialog->Hide();
			this->showSystemsButton->Enable(false);
			this->processToggleButton->Enable(false);
			wxMessageBox(_(e.what()));
		}
		try {
			this->resetVariables();
			this->resetFields();
			this->displayFrame->ReloadData();
			this->displayFrame->Refresh(false);
		}
		catch(exception & e) {
			wxMessageBox(_(e.what()));
		}
	}
}
/*
void MainForm::setupColourList() {
	// Systems declaration
	this->sysColourListCtrl->ClearAll();
	if ((this->sysColourList == NULL) ||
		((unsigned int)this->sysColourList->GetImageCount() != this->program.SysDecl().size())) {
		this->sysColourList = new wxImageList(ICON_W,ICON_H);
		vector<colour> palette; colour col;

		col.r = 1.f;	col.g = 0.f;	col.b = 0.f;	palette.push_back(col);
		col.r = 0.f;	col.g = 1.f;	col.b = 0.f;	palette.push_back(col);
		col.r = 0.f;	col.g = 0.f;	col.b = 1.f;	palette.push_back(col);
		col.r = 1.f;	col.g = 1.f;	col.b = 0.f;	palette.push_back(col);
		col.r = 1.f;	col.g = 0.f;	col.b = 1.f;	palette.push_back(col);
		col.r = 0.f;	col.g = 1.f;	col.b = 1.f;	palette.push_back(col);
		
		col.r = 0.5f;	col.g = 0.5f;	col.b = 0.f;	palette.push_back(col);
		col.r = 0.5f;	col.g = 0.f;	col.b = 0.5f;	palette.push_back(col);
		col.r = 0.5f;	col.g = 0.5f;	col.b = 0.5f;	palette.push_back(col);
		col.r = 0.f;	col.g = 0.5f;	col.b = 0.f;	palette.push_back(col);
		col.r = 0.f;	col.g = 0.f;	col.b = 0.5f;	palette.push_back(col);

		col.r = 0.75f;	col.g = 0.f;	col.b = 0.25f;	palette.push_back(col);

		vector<colour> colours;
		for (unsigned int i=0; i<this->program.SysDecl().size(); ++i) {
			colours.push_back(palette[i%palette.size()]);
			wxImage img = this->drawSystemImage(
				(unsigned char)(palette[i%palette.size()].r*255),
				(unsigned char)(palette[i%palette.size()].g*255),
				(unsigned char)(palette[i%palette.size()].b*255)
			);
			this->sysColourList->Add(wxBitmap(img));
		}
		this->displayFrame->SetColours(colours);
	}
	this->sysColourListCtrl->SetImageList(this->sysColourList,wxIMAGE_LIST_SMALL);
	for (unsigned int i=0; i<this->program.SysDecl().size(); ++i) {
		wxListItem item;
		item.SetId(i);
		item.SetText(this->program.SysDecl()[i].GetFirst().c_str());
		item.SetImage(i);
		this->sysColourListCtrl->InsertItem(item);
	}
}

wxImage MainForm::drawSystemImage(const unsigned char r, const unsigned char g, const unsigned char b) {
	wxImage img(ICON_W,ICON_H);
	float rx = img.GetWidth()/2.f, ry = img.GetHeight()/2.f;
	for (int y=0; y<img.GetHeight(); ++y)
		for (int x=0; x<img.GetWidth(); ++x)
			if (pow(x-rx,2)/pow(rx,2)+pow(y-ry,2)/pow(ry,2) <= 1)
				img.SetRGB(x,y,r,g,b);
			else
				img.SetRGB(x,y,0,0,1);
	img.SetMaskColour(0,0,1);
	return img;
}
*/

/*!
 * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RUN_TOGGLEBUTTON
 */

void MainForm::OnRunTogglebuttonClick( wxCommandEvent& event )
{
	this->fileMenu->Enable(ID_LOAD_PROGRAM_MENUITEM,!this->runToggleButton->GetValue());
	this->loadButton->Enable(!this->runToggleButton->GetValue());
////@begin wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RUN_TOGGLEBUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RUN_TOGGLEBUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_RESET_BUTTON
 */

void MainForm::OnResetButtonClick( wxCommandEvent& event )
{
	try {
		this->engine.Clear();
		this->engine.InitData(this->program,this->plugin_dirs);
		this->systems_dialog->SetData(this->program,this->engine.GetSystems());
		this->displayFrame->Refresh(false);
		this->resetVariables();
		this->resetFields();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_RESET_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_RESET_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SHOW_SYSTEMS_BUTTON
 */

void MainForm::OnShowSystemsButtonClick( wxCommandEvent& event )
{
	this->systems_dialog->Show();
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SHOW_SYSTEMS_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SHOW_SYSTEMS_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX1
 */

void MainForm::OnDisplayCheckboxClick( wxCommandEvent& event )
{
	try {
		if (event.IsChecked()) {
			this->systems_dialog->UpdateAllData(this->engine.GetSystems());
			this->epochNbLabel->SetLabel(wxString::Format("%d",this->epochNb));
			this->sampleNbLabel->SetLabel(wxString::Format("%d",this->sampleNb));
			if ((int)this->epochNb <= this->maxSupEpochsSpinCtrl->GetValue())
				this->learningStateLabel->SetLabel(_("in progress"));
			else
				this->learningStateLabel->SetLabel(_("done"));
			if (this->current_sample != NO_SAMPLE) {
				this->curSetLabel->SetLabel(_(this->sets[this->current_sample.first].GetName().c_str()));
				// Convert sample to string
				vector<string> sample;
				sample = this->sets[this->current_sample.first].GetSamples().GetSamplesData()[this->current_sample.second];
				string spl;
				for (unsigned int j=0; j<sample.size(); ++j) {
					if (!spl.empty()) spl += " ";
					spl += sample[j];
				}
				this->curInputLabel->SetLabel(_(spl.c_str()));
			}
			else {
				this->curSetLabel->SetLabel(_(""));
				this->curInputLabel->SetLabel(_(""));
			}
			// Update set list
			this->setSetsStatistics();
			// Update sample list
			this->setSampleList();
		}
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX1 in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX1 in MainForm. 
}

void MainForm::updateProcessButton() {
	bool enable = false;
	for (unsigned int i=0; i<this->sets.size(); ++i)
		enable |= !this->sets[i].GetSamples().GetSamplesData().empty();
	this->processToggleButton->Enable(enable);
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_ADD_EX_BUTTON
 */

void MainForm::OnAddSetButtonClick( wxCommandEvent& event )
{
	try {
		// Set default set name
		string name;
		{
			stringstream ss; ss << "Set " << (this->sets.size()+1);
			name = ss.str();
		}
		// Create empty set
		SampleSet new_set(name);
		this->sets.push_back(new_set);
		// Add set in list view
		wxListItem item;
		item.SetId(this->sets.size()+1);
		item.SetColumn(0);
		item.SetText(_(new_set.GetName().c_str()));
		this->setsListView->InsertItem(item);
		item.SetColumn(1);
		item.SetText("");
		this->setsListView->SetItem(item);
		item.SetColumn(2);
		item.SetText("");
		this->setsListView->SetItem(item);
		// Reset current processing
		this->epoch.clear();
		this->current_sample = NO_SAMPLE;
		// Eventually enable process button
		this->updateProcessButton();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_ADD_EX_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_ADD_EX_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_REMOVE_EX_BUTTON
 */

void MainForm::OnRemoveSetButtonClick( wxCommandEvent& event )
{
	try {
		vector<int> selections;
		for (long i = this->setsListView->GetFirstSelected(); i != -1; i = this->setsListView->GetNextSelected(i))
			selections.push_back((unsigned int)i);
		for (int i=selections.size()-1; i >= 0; --i) {
			vector<SampleSet>::iterator itor = this->sets.begin();
			for (int s=0; s<selections[i]; ++s) ++itor;
			this->sets.erase(itor);
			this->setsListView->DeleteItem(selections[i]);
			// Reset current processing
			this->epoch.clear();
			this->current_sample = NO_SAMPLE;
		}
		// Eventually disable process button
		this->updateProcessButton();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_REMOVE_EX_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_REMOVE_EX_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_CLEAR_EX_BUTTON
 */

void MainForm::OnClearSetButtonClick( wxCommandEvent& event )
{
	try {
		this->sets.clear();
		this->setsListView->DeleteAllItems();
		this->setsType->SetLabel(_(""));
		this->setsSize->SetLabel(_(""));
		wxListEvent evt; this->OnSetsListviewDeselected(evt);
		this->current_sample = NO_SAMPLE;
		// Reset current processing
		this->epoch.clear();
		this->current_sample = NO_SAMPLE;
		// Disables process button
		this->updateProcessButton();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_CLEAR_EX_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_CLEAR_EX_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON
 */

void MainForm::OnResetSetResultsButtonClick( wxCommandEvent& event )
{
	try {
		// Delete all results
		for (unsigned int i=0; i<this->sets.size(); ++i) {
			this->sets[i].ClearSamplesResults();
			// Delete results in sets list 
			wxListItem item;
			item.SetId(i);
			item.SetColumn(1);
			item.SetText(_(""));
			this->setsListView->SetItem(item);
			item.SetColumn(2);
			item.SetText(_(""));
			this->setsListView->SetItem(item);
		}
		// Delete results in sample list
		this->setSampleList();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_LIST_END_LABEL_EDIT event handler for ID_SETS_LISTVIEW
 */

void MainForm::OnSetsListviewEndLabelEdit( wxListEvent& event )
{
	try {
		this->sets[event.GetIndex()].Name() = string(event.GetText().c_str());
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_LIST_END_LABEL_EDIT event handler for ID_SETS_LISTVIEW in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_LIST_END_LABEL_EDIT event handler for ID_SETS_LISTVIEW in MainForm. 
}

/*!
 * wxEVT_COMMAND_LIST_ITEM_SELECTED event handler for ID_SETS_LISTVIEW
 */

void MainForm::OnSetsListviewSelected( wxListEvent& event )
{
	try {
		this->samplesPanel->Enable(true);
		this->setSampleList();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_LIST_ITEM_SELECTED event handler for ID_SETS_LISTVIEW in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_LIST_ITEM_SELECTED event handler for ID_SETS_LISTVIEW in MainForm.
}


/*!
 * wxEVT_COMMAND_LIST_ITEM_DESELECTED event handler for ID_SETS_LISTVIEW
 */

void MainForm::OnSetsListviewDeselected( wxListEvent& event )
{
	try {
		this->samplesPanel->Enable(false);
		this->samplesListView->DeleteAllItems();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_LIST_ITEM_DESELECTED event handler for ID_SETS_LISTVIEW in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_LIST_ITEM_DESELECTED event handler for ID_SETS_LISTVIEW in MainForm. 
}

void MainForm::setSetsStatistics() {
	for (unsigned int s_idx=0; s_idx<this->sets.size(); ++s_idx) {
		const vector< vector<double> > & results = this->sets[s_idx].GetSamplesResults();
		vector< vector<double> > av_out;
		for (unsigned int o=0; o<results.size(); ++o) {
			while (av_out.size() < results[o].size()) av_out.push_back(vector<double>());
				for (unsigned int r=0; r<results[o].size(); ++r)
					av_out[r].push_back(results[o][r]);
		}
		// Update sets view
		wxListItem item;
		item.SetId(s_idx);
		stringstream ss1, ss2;
		for (unsigned int r=0; r<av_out.size(); ++r) {
			double ave = Average(av_out[r]);
			ss1 << ((r>0)?" ":"") << ave;
			ss2 << ((r>0)?" ":"") << StdDevAve(av_out[r],ave);
		}
		item.SetColumn(1);
		item.SetText(_(ss1.str().c_str()));
		this->setsListView->SetItem(item);
		item.SetColumn(2);
		item.SetText(_(ss2.str().c_str()));
		this->setsListView->SetItem(item);
	}
}

void MainForm::setSampleList() {
	if (this->setsListView->GetFirstSelected() == -1) return;
	this->samplesListView->DeleteAllItems();
	long set_index = this->setsListView->GetFirstSelected();
	const SampleSet & set = this->sets[set_index];
	const SamplesHandler & samples = set.GetSamples();
	for (unsigned int i=0; i<samples.GetSamplesData().size(); ++i) {
		// Set sample
		string spl;
		for (unsigned int j=0; j<samples.GetSamplesData()[i].size(); ++j) {
			if (!spl.empty()) spl += " ";
			spl += samples.GetSamplesData()[i][j];
		}
		wxListItem item;
		item.SetId(i);
		item.SetColumn(0);
		item.SetText(_(spl.c_str()));
		this->samplesListView->InsertItem(item);
		// Set results
		stringstream ss;
		for (unsigned int j=0; j<set.GetSamplesResults()[i].size(); ++j) {
			if (!ss.str().empty()) ss << " ";
			ss << set.GetSamplesResults()[i][j];
		}
		item.SetColumn(1);
		item.SetText(_(ss.str().c_str()));
		this->samplesListView->SetItem(item);
	}
	this->samplesNumber->SetLabel(wxString::Format("%d",samples.GetSamplesData().size()));
	stringstream classification;
	for (unsigned int i=0; i<this->sets[set_index].GetClassification().size(); ++i)
		classification << ((i==0)?"":" ") << this->sets[set_index].GetClassification()[i];
	this->samplesClassification->SetValue(_(classification.str().c_str()));
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_ADD_CEX_BUTTON
 */

void MainForm::OnAddSamplesButtonClick( wxCommandEvent& event )
{
	try {
		if (this->setsListView->GetFirstSelected() == -1) return;
		wxString path = wxFileSelector("Select samples","samples","","spl","Sample files (*.spl)|*.spl|All files (*.*)|*.*",wxOPEN,this);
		if (!path.empty()) {
			SampleSet & set = this->sets[this->setsListView->GetFirstSelected()];
			set.AddSamplesFromFile(string(path.c_str()));
			for (unsigned int i=0; i<this->sets.size(); ++i) {
				if ((!this->sets[i].GetSamples().GetDataType().empty()) &&
					(this->sets[i].GetSamples().GetDataType() != set.GetSamples().GetDataType())) {
					set.ClearSamples();
					throw Exception("Sample type conflict between sets : " + this->sets[i].GetSamples().GetDataType()+" / " + set.GetSamples().GetDataType());
				}
			}
			this->setsType->SetLabel(_(set.GetSamples().GetDataType().c_str()));
			this->setsSize->SetLabel(wxString::Format("%d",set.GetSamples().GetDataSize()));
			this->samplesNumber->SetLabel(wxString::Format("%d",set.GetSamples().GetSamplesData().size()));
			// Set sample list
			this->setSampleList();
			// Reset current processing
			this->epoch.clear();
			this->current_sample = NO_SAMPLE;
			// Eventually enables process button
			this->updateProcessButton();
		}
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_ADD_CEX_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_ADD_CEX_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_REMOVE_CEX_BUTTON
 */

void MainForm::OnRemoveSamplesButtonClick( wxCommandEvent& event )
{
	try {
		if (this->setsListView->GetFirstSelected() == -1) return;
		SampleSet & set = this->sets[this->setsListView->GetFirstSelected()];
		vector<int> selections;
		for (long i = this->samplesListView->GetFirstSelected(); i != -1; i = this->samplesListView->GetNextSelected(i))
			selections.push_back((unsigned int)i);
		for (int i=selections.size()-1; i >= 0; --i)
			set.RemoveSamplesAt(selections[i]);
		this->samplesNumber->SetLabel(wxString::Format("%d",set.GetSamples().GetSamplesData().size()));
		// Set sample list
		this->setSampleList();
		// Reset current processing
		this->epoch.clear();
		this->current_sample = NO_SAMPLE;
		// Eventually disables process button
		this->updateProcessButton();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_REMOVE_CEX_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_REMOVE_CEX_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_CLEAR_CEX_BUTTON
 */

void MainForm::OnClearSamplesButtonClick( wxCommandEvent& event )
{
	try {
		if (this->setsListView->GetFirstSelected() == -1) return;
		SampleSet & set = this->sets[this->setsListView->GetFirstSelected()];
		set.ClearSamples();
		this->samplesNumber->SetLabel(wxString::Format("%d",0));
		// Set sample list
		this->setSampleList();
		// Reset current processing
		this->epoch.clear();
		this->current_sample = NO_SAMPLE;
		// Disables process button
		this->updateProcessButton();
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_CLEAR_CEX_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_TRAINING_CLEAR_CEX_BUTTON in MainForm. 
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_FORCE_SAMPLE_BUTTON
 */
/*
void MainForm::OnForceSampleButtonClick( wxCommandEvent& event )
{
	try {
		if (this->setsListView->GetFirstSelected() == -1) return;
		if (this->samplesListView->GetFirstSelected() == -1) return;
		this->forced_sample = pair<int,int>(this->setsListView->GetFirstSelected(),this->samplesListView->GetFirstSelected());
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_FORCE_SAMPLE_BUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_FORCE_SAMPLE_BUTTON in MainForm. 
}
*/

/*!
 * wxEVT_COMMAND_TEXT_UPDATED event handler for ID_CLASS_SAMPLES_TEXTCTRL
 */

void MainForm::OnClassSamplesTextctrlUpdated( wxCommandEvent& event )
{
	if (this->setsListView->GetFirstSelected() == -1) return;
	long set_index = this->setsListView->GetFirstSelected();
	vector<double> classification;
	stringstream ss;
	ss << event.GetString().c_str();
	while (!ss.eof()) {
		double c; ss >> c;
		classification.push_back(c);
	}
	this->sets[set_index].SetClassification(classification);
////@begin wxEVT_COMMAND_TEXT_UPDATED event handler for ID_CLASS_SAMPLES_TEXTCTRL in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_TEXT_UPDATED event handler for ID_CLASS_SAMPLES_TEXTCTRL in MainForm. 
}

/*!
 * wxEVT_COMMAND_SPINCTRL_UPDATED event handler for ID_DISP_BUF_SPINCTRL
 */

void MainForm::OnDispBufSpinctrlUpdated( wxSpinEvent& event )
{
	try {
		for (unsigned int i=0; i<this->classCurves.size(); ++i)
			this->classCurves[i]->SetBufferSize(this->dspBufSpinCtrl->GetValue());
		for (unsigned int i=0; i<this->outputCurves.size(); ++i)
			this->outputCurves[i]->SetBufferSize(this->dspBufSpinCtrl->GetValue());
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_COMMAND_SPINCTRL_UPDATED event handler for ID_DISP_BUF_SPINCTRL in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_SPINCTRL_UPDATED event handler for ID_DISP_BUF_SPINCTRL in MainForm. 
}

/*!
 * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_PROCESS_TOGGLEBUTTON
 */

void MainForm::OnProcessTogglebuttonClick( wxCommandEvent& event )
{
	this->fileMenu->Enable(ID_LOAD_DATA_MENUITEM,!event.IsChecked());
	this->addSetsButton->Enable(!event.IsChecked());
	this->removeSetsButton->Enable(!event.IsChecked());
	this->clearSetsButton->Enable(!event.IsChecked());
	this->addSamplesButton->Enable(!event.IsChecked());
	this->removeSamplesButton->Enable(!event.IsChecked());
	this->clearSamplesButton->Enable(!event.IsChecked());
////@begin wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_PROCESS_TOGGLEBUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_PROCESS_TOGGLEBUTTON in MainForm. 
}

/*!
 * wxEVT_IDLE event handler for ID_RUN_TOGGLEBUTTON
 */

void MainForm::OnIdle( wxIdleEvent& event )
{
	try {
		// If running
		if (this->runToggleButton->GetValue()) {
			SCSystem & universe = this->engine.Universe();
			if (this->processToggleButton->GetValue()) {
				if ((int)this->iter_counter > this->ipsSpinCtrl->GetValue()) {
					bool new_epoch = false;
					// See whether a new epoch should be created
					if (this->epoch.empty()) {
						for (unsigned int i=0; i<this->sets.size(); ++i)
							for (unsigned int j=0; j<this->sets[i].GetSamples().GetSamplesData().size(); ++j)
								this->epoch.push_back(pair<int,int>(i,j));
						++this->epochNb;
						new_epoch = true;
					}
					// Reset iteration per sample counter
					this->iter_counter = 0;
					// Take a sample
					this->current_sample = this->epoch[rand() % this->epoch.size()];
					this->epoch.erase(find(this->epoch.begin(),this->epoch.end(),this->current_sample));
					const vector<string> & sample = this->sets[this->current_sample.first].GetSamples().GetSamplesData()[this->current_sample.second];
					// Sets the universe
					ANNPluginInterface::Evaluate(universe,sample,((!this->batchRadioButton->GetValue()) || new_epoch));
					// Increment number of time a sample has been processed
					++this->sampleNb;
				}
				if (((int)this->epochNb <= this->maxSupEpochsSpinCtrl->GetValue()) &&
					((int)this->iter_counter == this->learnSpikeSpinCtrl->GetValue()))
					ANNPluginInterface::Learn(universe,this->sets[this->current_sample.first].GetClassification());
			}
			// --- Applies a systemic computation ---
			this->engine.Iterate();
			++this->iter_counter;
			// Get the universe output
			vector<double> output = ANNPluginInterface::GetOutput(universe);
			// Set it in the right curve
			if (!output.empty()) {
				while (this->outputCurves.size() < output.size()) {
					wxVectorIndexedPlotCurve * curve = new wxVectorIndexedPlotCurve(0,CURVE_MIN,CURVE_MAX,this->dspBufSpinCtrl->GetValue());
					curve->SetPenSelected(*wxRED_PEN);
					curve->SetPenNormal(*wxRED_PEN);
					if (this->outputCurves.size()>0)
						curve->AddPoints(vector<double>(this->outputCurves[0]->GetPoints().size(),-2.));
					this->outputCurves.push_back(curve);
					this->setPlot->Add(curve);
				}
				for (unsigned o=0; o<output.size(); ++o)
					this->outputCurves[o]->AddPoint(output[o]);
				if ((this->current_sample.first >= 0) && (this->current_sample.first < (int)this->sets.size())) {
					while (this->classCurves.size() < this->sets[this->current_sample.first].GetClassification().size()) {
						wxVectorIndexedPlotCurve * curve = new wxVectorIndexedPlotCurve(0,CURVE_MIN,CURVE_MAX,this->dspBufSpinCtrl->GetValue());
						curve->SetPenSelected(*wxGREEN_PEN);
						curve->SetPenNormal(*wxGREEN_PEN);
						if (this->outputCurves.size()>0)
							curve->AddPoints(vector<double>(this->outputCurves[0]->GetPoints().size(),-2.));
						this->classCurves.push_back(curve);
						this->setPlot->Add(curve);
					}
					for (unsigned int c=0; c<this->sets[this->current_sample.first].GetClassification().size(); ++c)
						this->classCurves[c]->AddPoint(this->sets[this->current_sample.first].GetClassification()[c]);
					if ((int)this->iter_counter >= this->ipsSpinCtrl->GetValue())
						this->sets[this->current_sample.first].SetSamplesResultsAt(this->current_sample.second,output);
				}
			}
			// --- Update all data ---
			if (this->displayCheckBox->IsChecked()) {
				// Context number label
				this->nbCtxLabel->SetLabel(wxString::Format("%d",this->engine.GetContexts().size()));
				// If new sample has been set
				if (this->iter_counter == 1) {
					// Update universe view
					for (unsigned int s=0; s<this->engine.GetNbSystems(); ++s) {
						if (&this->engine.GetSystem(s) == &universe) {
							this->systems_dialog->Update(s,universe);
							break;
						}
					}
					// Update state fields
					this->epochNbLabel->SetLabel(wxString::Format("%d",this->epochNb));
					this->sampleNbLabel->SetLabel(wxString::Format("%d",this->sampleNb));
					if ((int)this->epochNb <= this->maxSupEpochsSpinCtrl->GetValue())
						this->learningStateLabel->SetLabel(_("in progress"));
					else
						this->learningStateLabel->SetLabel(_("done"));
					// Update sample display
					if (this->current_sample.first >= 0) {
						this->curSetLabel->SetLabel(_(this->sets[this->current_sample.first].GetName().c_str()));
						// Convert sample to string
						const vector<string> & sample = this->sets[this->current_sample.first].GetSamples().GetSamplesData()[this->current_sample.second];
						string spl;
						for (unsigned int j=0; j<sample.size(); ++j) {
							if (!spl.empty()) spl += " ";
							spl += sample[j];
						}
						this->curInputLabel->SetLabel(_(spl.c_str()));
					}
				}
				// Involved systems view
				const SComputationInfo & comp = this->engine.GetLastComputation();
				if (comp.has_computed && this->systems_dialog->IsShown()) {
					this->systems_dialog->Update(comp.sys1_idx,	this->engine.GetSystem(comp.sys1_idx));
					this->systems_dialog->Update(comp.ctx_idx,	this->engine.GetSystem(comp.ctx_idx));
					this->systems_dialog->Update(comp.sys2_idx,	this->engine.GetSystem(comp.sys2_idx));
				}
				// Display
				this->displayFrame->Refresh(false);
				// Display the output
				this->setPlot->RedrawEverything();
				// Update the potential result
				if (this->processToggleButton->GetValue() && !output.empty() &&
					(this->current_sample.first >= 0) && ((int)this->iter_counter >= this->ipsSpinCtrl->GetValue())) {
					stringstream ss;
					for (unsigned int o=0; o<output.size(); ++o)
						ss << ((o>0)?" ":"") << output[o];
					wxListItem item;
					// Update samples view
					if (this->current_sample.first == this->setsListView->GetFirstSelected()) {
						item.SetId(this->current_sample.second);
						item.SetColumn(1);
						item.SetText(_(ss.str().c_str()));
						this->samplesListView->SetItem(item);
					}
					this->setSetsStatistics();
				}
			}
			event.RequestMore();
		}
	}
	catch(exception & e) {
		wxMessageBox(_(e.what()));
	}
////@begin wxEVT_IDLE event handler for ID_RUN_TOGGLEBUTTON in MainForm.
	// Before editing this code, remove the block markers.
	event.Skip();
////@end wxEVT_IDLE event handler for ID_RUN_TOGGLEBUTTON in MainForm. 
}

void MainForm::resetVariables() {
	this->iter_counter = 0x00FFFFFF;
	this->epochNb = 0;
	this->sampleNb = 0;
	this->current_sample = NO_SAMPLE;
	this->epoch.clear();
	for (unsigned int i=0; i<this->sets.size(); ++i)
		this->sets[i].ClearSamplesResults();
	for (unsigned int i=0; i<this->classCurves.size(); ++i)
		this->setPlot->Delete(this->classCurves[i]);
	this->classCurves.clear();
	for (unsigned int i=0; i<this->outputCurves.size(); ++i)
		this->setPlot->Delete(this->outputCurves[i]);
	this->outputCurves.clear();
}

void MainForm::resetFields() {
	this->epochNbLabel->SetLabel(wxString::Format("%d",this->epochNb));
	this->sampleNbLabel->SetLabel(wxString::Format("%d",this->sampleNb));
	this->curSetLabel->SetLabel(_(""));
	this->curInputLabel->SetLabel(_(""));
	this->learningStateLabel->SetLabel(_("..."));
	for (unsigned int i=0; i<this->sets.size(); ++i) {
		// Reset stats
		wxListItem item;
		item.SetId(i);
		item.SetColumn(1);
		item.SetText("");
		this->setsListView->SetItem(item);
		item.SetColumn(2);
		item.SetText("");
		this->setsListView->SetItem(item);
	}
	this->setSampleList();
	this->setPlot->Refresh();
}

/*
void MainForm::resetError() {
	int width, height;
	this->errorStaticBitmap->GetClientSize(&width,&height);
	this->errorBitmap = wxBitmap(width,height);
	wxMemoryDC dc;	
	dc.SelectObject(this->errorBitmap);
	dc.SetBackground(wxBrush(wxColour(255,235,225)));
	dc.Clear();
	dc.SelectObject(wxNullBitmap);
	this->errorStaticBitmap->SetBitmap(this->errorBitmap);
}

void MainForm::setNewError(float value) {
	if ((value < 0.f) || (value > 1.f)) {
		ostringstream ss;
		ss << "Error value should be within the range [0,1], found: " << value;
		throw AssertionException(ss.str());
	}
	// Get DC
	wxMemoryDC dc;
	dc.SelectObject(this->errorBitmap);
	// Shift the image of one pixel on the left to display the new value
	dc.Blit(0,0,this->errorBitmap.GetWidth()-1,this->errorBitmap.GetHeight(),&dc,1,0);
	dc.SetPen(wxPen(wxColour(255,235,225)));
	dc.DrawLine(this->errorBitmap.GetWidth()-1,0,this->errorBitmap.GetWidth()-1,this->errorBitmap.GetHeight());
	// Add the new output
	dc.SetPen(wxPen(wxColour(255,128,0)));
	dc.DrawPoint(this->errorBitmap.GetWidth()-1,(unsigned int)((1.f-value)*(this->errorBitmap.GetHeight()-1)));
	// Deselect
	dc.SelectObject(wxNullBitmap);
	// Update bitmap
	this->errorStaticBitmap->SetBitmap(this->errorBitmap);
}

void MainForm::resetOutput() {
	int width, height;
	this->outputStaticBitmap->GetClientSize(&width,&height);
	this->outputBitmap = wxBitmap(width,height);
	wxMemoryDC dc;	
	dc.SelectObject(this->outputBitmap);
	dc.SetBackground(wxBrush(wxColour(255,235,225)));
	dc.Clear();
	dc.SelectObject(wxNullBitmap);
	this->outputStaticBitmap->SetBitmap(this->outputBitmap);
}

void MainForm::setNewOutput(float value) {
	if ((value < 0.f) || (value > 1.f)) {
		ostringstream ss;
		ss << "Output value should be within the range [0,1], found: " << value;
		throw AssertionException(ss.str());
	}
	// Get DC
	wxMemoryDC dc;
	dc.SelectObject(this->outputBitmap);
	// Shift the image one pixel on the left to display the new value
	dc.Blit(0,0,this->outputBitmap.GetWidth()-1,this->outputBitmap.GetHeight(),&dc,1,0);
	dc.SetPen(wxPen(wxColour(255,235,225)));
	dc.DrawLine(this->outputBitmap.GetWidth()-1,0,this->outputBitmap.GetWidth()-1,this->outputBitmap.GetHeight());
	// Add the new output
	dc.SetPen(wxPen(wxColour(0,128,255)));
	dc.DrawPoint(this->outputBitmap.GetWidth()-1,(unsigned int)((1.f-value)*(this->outputBitmap.GetHeight()-1)));
	// Deselect
	dc.SelectObject(wxNullBitmap);
	// Update bitmap
	this->outputStaticBitmap->SetBitmap(this->outputBitmap);
}*/


